package com.auto.api.http.service;

import com.auto.api.admin.api.ApiInfoApi;
import com.auto.api.admin.dto.AdminApiDTO;
import com.auto.api.admin.dto.BeansDTO;
import com.auto.api.admin.dto.BeansDependenciesDTO;
import com.auto.api.admin.dto.ApiInfoReqDTO;
import com.auto.api.core.entity.ApiInfo;
import com.auto.api.core.entity.BaseApiInfo;
import com.auto.api.common.utils.BeanMapper;
import com.auto.api.core.service.ApplicationInfoService;
import com.auto.api.core.service.ApiInfoService;
import com.auto.api.core.util.SpringContextHolder;
import com.google.common.collect.Lists;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

/**
 * @program:
 * @description:
 * @author: liangshf
 * @create: 2022-01-10
 */
@Component
public class ApiInfoServiceImpl implements ApiInfoService {

    @Resource
    private ApiInfoApi mappingApi;

    @Resource(name = "applicationInfoService")
    private ApplicationInfoService applicationInfoService;

    @Override
    public void saveApiItem(List<ApiInfo> items) {
        AdminApiDTO adminApi = new AdminApiDTO();
        adminApi.setAdminApiList(buildApiList(items));
        adminApi.setBeansList(buildBeanList());
        //保存bean组件以及依赖关系
        mappingApi.saveApiList(adminApi);
    }

    @Override
    public BaseApiInfo getApiByUrl(String url) {
        return BeanMapper.map(mappingApi.getApiByUrl(url).getData(), BaseApiInfo.class);
    }

    private List<ApiInfoReqDTO> buildApiList(List<ApiInfo> methodItems) {
        List<ApiInfoReqDTO> mockMappingList = Lists.newArrayList();
        methodItems.forEach(i -> {
            ApiInfoReqDTO mockMappingDTO = BeanMapper.map(i, ApiInfoReqDTO.class);
            mockMappingDTO.setApplicationName(applicationInfoService.getApplicationInfo().getApplicationName());
            mockMappingDTO.setPort(applicationInfoService.getApplicationInfo().getPort());
            mockMappingList.add(mockMappingDTO);
        });
        return mockMappingList;
    }

    private List<BeansDTO> buildBeanList() {
        ApplicationContext applicationContext = SpringContextHolder.getApplicationContext();
        Assert.notNull(applicationContext);
        List<BeansDTO> beansList = Lists.newArrayList();
        ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            BeansDTO beansDTO = new BeansDTO();
            beansDTO.setApplicationName(applicationInfoService.getApplicationInfo().getApplicationName());
            beansDTO.setPort(applicationInfoService.getApplicationInfo().getPort());
            beansDTO.setBeanName(beanName);
            BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);
            beansDTO.setType(beanDefinition.getBeanClassName() == null ? beanName: beanDefinition.getBeanClassName());
            beansDTO.setScopeType(beanDefinition.getScope());
            beansList.add(beansDTO);
            if (beanFactory.getDependenciesForBean(beanName) == null) {
                continue;
            }
            List<BeansDependenciesDTO> beansDependenciesDTOList = Lists.newArrayList();
            for (String dependOnBean : beanFactory.getDependenciesForBean(beanName)) {
                BeansDependenciesDTO beansDependenciesDTO = new BeansDependenciesDTO();
                beansDependenciesDTO.setApplicationName(applicationInfoService.getApplicationInfo().getApplicationName());
                beansDependenciesDTO.setPort(applicationInfoService.getApplicationInfo().getPort());
                if (dependOnBean.indexOf(".") != -1) {
                    dependOnBean = dependOnBean.substring(dependOnBean.lastIndexOf(".") + 1 , dependOnBean.length());
                }
                beansDependenciesDTO.setDependencieName(dependOnBean);
                beansDependenciesDTOList.add(beansDependenciesDTO);
            }
            beansDTO.setBeansDependenciesList(beansDependenciesDTOList);
        }
        return beansList;
    }
}